﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PloobsEngine.SceneControl;
using PloobsEngine.Physics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Input;
using Microsoft.Xna.Framework;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.Modelo;
using PloobsEngine.Material;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Utils;
using PloobsEngine.Features;
using PloobsEngine.Commands;
using PloobsEngineDemo3;
using PloobsEngine.Light;
using PloobsEngine.Physic.PhysicObjects.BepuObject;
using BEPUphysics.ForceFields;

namespace Etapa1.Screens
{
    public class TornadoScreen : SceneScreen
    {
        private BepuPhysicWorld physicWorld;
        private BrutalForceWorld mundo;
        private EngineStuff engine;        
        ICamera cam;
        BoundingBoxForceFieldShape shape;
        TornadoObject tornado;

        public TornadoScreen(EngineStuff es)
        {
            this.engine = es;
            physicWorld = new BepuPhysicWorld();
            mundo = new BrutalForceWorld(physicWorld);                        
            engine.Game.IsFixedTimeStep = true;
        }

        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {
            var dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
            Vector3 increment = StaticRandom.RandomDirection() * 3 * dt;
            //Move the detection shape as well.
            shape.BoundingBox = new BoundingBox(shape.BoundingBox.Min + increment, shape.BoundingBox.Max + increment);
            tornado.Position += increment;
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
        }

        public override void LoadContent(EngineStuff es)
        {            
            InputAdvanced inp = new InputAdvanced(engine);
            engine.AddComponent(inp);

            base.LoadContent(es);            

            #region Models    
                
                shape = new BoundingBoxForceFieldShape(new BoundingBox(new Vector3(-100, -20, -40), new Vector3(50, 120, 40)));
                tornado = new TornadoObject(shape, (shape.BoundingBox.Min + shape.BoundingBox.Max) / 2, new Vector3(0, 1, 0),
                                      150, false, 50, 10, 200, 200, 80, 2000, 90, 20);

                tornado.ForceWakeUp = true;
                physicWorld.AddUpdateableObject(tornado);
                
                int numColumns = 10;
                int numRows = 10;
                int numHigh = 2;
                float separation = 5f;                
                for (int i = 0; i < numRows; i++)
                    for (int j = 0; j < numColumns; j++)
                        for (int k = 0; k < numHigh; k++)
                        {

                            {
                                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cubo", "..\\Content\\Textures\\white");
                                sm.LoadModelo();
                                BoxObject pi = new BoxObject(new Vector3(separation * i - numRows * separation / 2,150 + k * separation,separation * j - numColumns * separation / 2), 1, StaticRandom.RandomBetween(5,50), new Vector3(1));
                                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                                shader.SpecularIntensity = 0;
                                shader.SpecularPower = 0;
                                shader.Initialize();
                                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                                IObject obj3 = new SimpleObject(mat, pi, sm);
                                mundo.AddObject(obj3);
                            }
                            
                        }




            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cenario");
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(Vector3.Zero, sm);                
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                shader.Initialize();
                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }
            

            #endregion            

            cam = new CameraFirstPerson(true);            
            cam.FarPlane = 3000;

            LightThrowBepu lt = new LightThrowBepu(mundo, engine);         

            #region NormalLight
            DirectionalLight ld1 = new DirectionalLight(Vector3.Left, Color.White);
            DirectionalLight ld2 = new DirectionalLight(Vector3.Right, Color.White);
            DirectionalLight ld3 = new DirectionalLight(Vector3.Backward, Color.White);
            DirectionalLight ld4 = new DirectionalLight(Vector3.Forward, Color.White);
            DirectionalLight ld5 = new DirectionalLight(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            mundo.AddLight(ld1);
            mundo.AddLight(ld2);
            mundo.AddLight(ld3);
            mundo.AddLight(ld4);
            mundo.AddLight(ld5);
            #endregion

            ////Criacao de uma Tecnica
            DeferredRenderTechnic dr = new DeferredRenderTechnic(engine);
            
            IRenderTechnic[] rt = new IRenderTechnic[] { dr };
            this.RenderTechnics = rt;
            mundo.AddCamera(cam);
            this.World = mundo;
        }        
    }
}

